/* GLTexture.cpp
 *
 * --
 * Copyright (c) 2012, Christophe Huriaux
 * Distributed under the terms of the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * --
 */

#include <graphics/GLTexture.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <debug/logger.h>

GLTexture::GLTexture(SDLSurface& s, unsigned int eWidth, unsigned int eHeight)
	: id(-1), rawSurface(s), elementWidth(eWidth), elementHeight(eHeight),
	  textureVertices(new GLVertexDataLocal<vector2d>())
{
	elementCountX = s.getWidth() / eWidth;
	elementCountY = s.getHeight() / eHeight;
	ratioX = (double)eWidth / s.getWidth();
	ratioY = (double)eHeight / s.getHeight();
	pitch = s.getHeight() / eHeight;
	initVertices();
}

GLTexture::GLTexture(SDL_Surface* s, unsigned int eWidth, unsigned int eHeight)
	: id(-1), rawSurface(s), elementWidth(eWidth), elementHeight(eHeight),
	  textureVertices(new GLVertexDataLocal<vector2d>())
{
	elementCountX = rawSurface.getWidth() / eWidth;
	elementCountY = rawSurface.getHeight() / eHeight;
	ratioX = (double)eWidth / rawSurface.getWidth();
	ratioY = (double)eHeight / rawSurface.getHeight();
	pitch = rawSurface.getHeight() / eHeight;
	initVertices();
}

GLTexture::GLTexture(SDLSurface& s, unsigned int eWidth, unsigned int eHeight,
	GLVertexData<vector2d>* verticesObject)
	: id(-1), rawSurface(s), elementWidth(eWidth), elementHeight(eHeight),
	  textureVertices(verticesObject)
{
	elementCountX = s.getWidth() / eWidth;
	elementCountY = s.getHeight() / eHeight;
	ratioX = (double)eWidth / s.getWidth();
	ratioY = (double)eHeight / s.getHeight();
	pitch = s.getHeight() / eHeight;
	initVertices();
}

GLTexture::GLTexture(SDL_Surface* s, unsigned int eWidth, unsigned int eHeight,
	GLVertexData<vector2d>* verticesObject)
	: id(-1), rawSurface(s), elementWidth(eWidth), elementHeight(eHeight),
	  textureVertices(verticesObject)
{
	elementCountX = rawSurface.getWidth() / eWidth;
	elementCountY = rawSurface.getHeight() / eHeight;
	ratioX = (double)eWidth / rawSurface.getWidth();
	ratioY = (double)eHeight / rawSurface.getHeight();
	pitch = rawSurface.getHeight() / eHeight;
	initVertices();
}


void
GLTexture::initVertices()
{
	vector2d* v = new vector2d[(elementCountX+1)*(elementCountY+1)];
	textureVertices->setGeometry((elementCountX+1)*(elementCountY+1), 2);

	int i = 0;
	for (float y = 0; y <= 1; y += ratioY)
		for (float x = 0; x <= 1; x += ratioX)
			v[i++] = vector2d(x, y);

	if (textureVertices == NULL)
		std::runtime_error("textureVertices GLVertexData not initialized");

	textureVertices->init(v);

	delete[] v;
}

double
GLTexture::getCoordX(GLTexCoord corner, unsigned int element)
{
	return (element%pitch + ((corner&TEX_RIGHT)?1:0)) * ratioX;
}

double
GLTexture::getCoordY(GLTexCoord corner, unsigned int element)
{
	return 1- (element/pitch + ((corner&TEX_BOTTOM)?1:0)) * ratioY;
}


vector2d
GLTexture::getCoord(GLTexCoord corner, unsigned int element)
{
	double x = (element%pitch + ((corner&TEX_RIGHT)?1:0)) * ratioX,
			y = 1 - (element/pitch + ((corner&TEX_BOTTOM)?1:0)) * ratioY;

	return vector2d(x, y);
}

void
GLTexture::texCoord2d(GLTexCoord corner, unsigned int element)
{
	double x = (element%pitch + ((corner&TEX_RIGHT)?1:0)) * ratioX,
			y = 1 - (element/pitch + ((corner&TEX_BOTTOM)?1:0)) * ratioY;

	glTexCoord2d(x, y);
}

void
GLTexture::load()
{
	rawSurface.convertToRGBA8();
	rawSurface.flip();
	logg(debug) << "id avant: " << id << logg::endl;
	glGenTextures(1, (GLuint*)&id);
	logg(debug) << "id après: " << id << logg::endl;
	glBindTexture(GL_TEXTURE_2D, id);

	logg(debug) << "Loading a " << rawSurface.getWidth() << "x" <<
		rawSurface.getHeight() << " texture" << logg::endl;

	//gluBuild2DMipmaps(GL_TEXTURE_2D, 4, rawSurface.getWidth(), rawSurface.getHeight(),
	//	GL_RGBA, GL_UNSIGNED_BYTE, rawSurface.rawData());

	glTexImage2D(GL_TEXTURE_2D, 0, 4, rawSurface.getWidth(), rawSurface.getHeight(),
		0, GL_RGBA, GL_UNSIGNED_BYTE, rawSurface.rawData());
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

void
GLTexture::use()
{
	glBindTexture(GL_TEXTURE_2D, id);
}
